﻿import mx.controls.ComboBox;
import mx.controls.NumericStepper;

import flash.filters.DropShadowFilter;

import com.yourdomain.spreadshop.gui.GUI;
import com.yourdomain.spreadshop.gui.mod.lib.Module;
import com.yourdomain.spreadshop.gui.mod.lib.ScrollBar;
import com.yourdomain.spreadshop.gui.mod.lib.LoaderAnimation;

import net.spreadshirt.logger.Logger;

/**
 * The ShoppingCart class represents the shopping basket with a list
 * of items to order. The user is able to change the size and the number
 * of pieces of every item.
 */
class com.yourdomain.spreadshop.gui.mod.ShoppingCart {

	// The reference to the swf file.
	private static var _SWF:String = "spreadshop_shoppingCart.swf";

	// Various visual settings.
	private static var _POSITION:Object = { x: 80, y: 80 };
	private static var _LABEL_TITLE:String = "Warenkorb";
	private static var _LABEL_SUBMIT:String = "Jetzt Bestellen";
	private static var _LABEL_SIZE:String = "Größe: <b>[size]</b>";
	private static var _LABEL_QUANTITY:String = "<b>[quantity]</b> x";
	private static var _LINK_TNC:String = " Ich bin mit den"
		+" <a href=\"asfunction:[function]\">[ <b>AGBs</b> ]</a>"
		+" einverstanden";
	private static var _INFO_ACCEPT_TNC:String = ""
		+"<b>Bestellvorgang kann nicht gestartet werden!</b>\n\n"
		+"Bitte lesen und akzeptieren sie unsere allgemeinen "
		+"Geschäftsbedingungen.";

	// The reference to the GUI main class.
	private var _gui:GUI;

	// The movie clip container.
	private var _clip:MovieClip;

	// A variable that's containing all the items to show.
	private var _items:Array;

	// Some variables that's saving the id of the selected item.
	private var _selectedItem:Number = null;
	private var _selectedClip:MovieClip;

	/**
	 * ShoppingCart Constructor
	 */
	public function ShoppingCart(
		gui:GUI,
		clip:MovieClip,
		level:Number
	) {
		// Connects with the GUI instance.
		_gui = gui;
		// Creates a clip and set its position on the stage.
		_clip = clip.createEmptyMovieClip("shoppingCart", level);
		// Creates the listener to watch the loading in progress.
		var mclListener:Object = new Object();
		mclListener.timer = [0, 0];
		mclListener.onLoadStart = function(target:MovieClip):Void {
		    this.timer[0] = getTimer();
		    Logger.getLog().info("GUI - ShoppingCart: start loading");
		};
		mclListener.onLoadComplete = function(target:MovieClip):Void {
			this.timer[1] = getTimer();
		};
		mclListener.shoppingCart = this;
		mclListener.onLoadInit = function(target:MovieClip):Void {
			var timer:Number = this.timer[1] - this.timer[0];
			var bytes:Number = target.getBytesLoaded();
			Logger.getLog().info("GUI - ShoppingCart: "
				+ bytes +" Bytes loaded in "+ timer +" ms.");
			this.shoppingCart.setup();
		};
		// Creates the loader and attachs the listener object.
		var mcLoader:MovieClipLoader = new MovieClipLoader();
		mcLoader.addListener(mclListener);
		mcLoader.loadClip(_gui.swf_path + _SWF, _clip);
	}

	/**
	 * Hides the module
	 */
	public function hide():Void {
		_clip.shoppingCart.hide();
	}

	/**
	 * Setup detail view
	 */
	private function setup():Void {
		_gui.initModuleDone("initShoppingCart");
		// Creates an alias to the shopping cart movie clip.
		var clip:MovieClip = _clip.shoppingCart;
		// Setup modul.
		var module:Module = new Module(
			_gui,
			clip,
			false,
			_LABEL_TITLE,
			_POSITION.x,
			_POSITION.y
		);
		// Hides the options ground shape.
		clip.gound.options._visible = false;
		// Clears total gross and currency textfields.
		clip.gross.tf.text = "";
		clip.currency.tf.text = "";
		// Setup terms and conditions checkbox.
		clip.tnctext.tf.htmlText = _LINK_TNC
			.split("[function]").join("showAGB");
		clip.tnctext.shoppingCart = this;
		clip.tnctext.showAGB = function():Void {
			this.shoppingCart._gui.showTNC();
		};
		clip.tnc.tabEnabled = false;
		var tncListener:Object = new Object();
		tncListener.shoppingCart = this;
		tncListener.click = function(evt:Object) {
			if(evt.target.selected) {
				this.shoppingCart._gui.acceptTNC();
			}
		};
		clip.tnc.addEventListener("click", tncListener);
		// Setup the submit button.
		clip.submit.tabEnabled = false;
		clip.submit.label = _LABEL_SUBMIT;
		clip.submit.color = 0x0099ff;
		clip.submit.tnc = clip.tnc;
		clip.submit.strInfo = _INFO_ACCEPT_TNC;
		clip.submit.shoppingCart = this;
		clip.submit.onPress = function():Void {
			if(this.tnc.selected) {
				this.shoppingCart._gui.submitOrder();
			} else {;
				this.shoppingCart._gui.showInfo(this.strInfo);
			}
		};
	}

	/**
	 * Show the basket
	 */
	public function showBasket(basket:Object):Void {
		// Creates an alias to the shopping cart.
		var cart:MovieClip = _clip.shoppingCart;
		// Shows the shopping cart movie clip.
		cart.setToFront();
		// Set total gross.
		cart.gross.tf.text = transformGross(basket.gross_total);
		// Set total currency.
		cart.currency.tf.text = basket.currency;
		// Shows the items in the basket.
		showItems(basket.items);
	}

	/**
	 * Show the basket items.
	 */
	private function showItems(items:Array):Void {
		// Hide options.
		_clip.shoppingCart.options._visible = false;
		_clip.shoppingCart.ground.options._visible = false;
		// Creates an alias to the shopping cart items container clip.
		var clip:MovieClip = _clip.shoppingCart.items.container;
		// Remove all items.
		for(var i:String in clip) {
			if(typeof clip[i] == "movieclip"
				&& clip[i]._name.substr(0, 4) == "item"
				&& clip[i]._name != "item0"
			) {
				clip[i].removeMovieClip();
			}
		}
		// Shows or hides the first item.
		clip.item0._visible = (items.length > 0);
		// Creates new items list.
		_items = new Array();
		for(var i:Number = 0; i < items.length; i++) {
			if(i > 0) {
				clip.item0.duplicateMovieClip("item"+ i, i);
			}
			var mc:MovieClip = clip["item"+ i];
			mc._y = 60 * i;
			// Starts loading the picture.
			loadItemPic(mc, items[i]);
			// Get article item data by ID.
			var article_item:Object = _gui.getArticle(items[i].article_id);
			// Remember clip id.
			mc.id = i;
			// Show the items name in the title textfield.
			mc.info.title.tf.text = article_item.name;
			// Show the gross.
			mc.info.gross.tf.text = transformGross(items[i].gross);
			// Show the currency.
			mc.info.currency.tf.text = items[i].currency;
			// Set the quantity.
			mc.strQuantity = _LABEL_QUANTITY;
			mc.setQuantity = function(quantity:Number):Void {
				this.info.quantity.tf.htmlText = this.strQuantity
					.split("[quantity]").join(quantity);
			};
			mc.setQuantity(items[i].quantity);
			// Setup the sizes.
			mc.sizes = article_item.producttype_sizes.getAllItems();
			mc.strSize = _LABEL_SIZE;
			mc.setSize = function(size_id:Number):Void {
				var size:String;
				for(var s:Number = 0; s < this.sizes.length; s++) {
					if(size_id == this.sizes[s].producttype_size_id) {
						size = this.sizes[s].name;
						break;
					}
				}
				this.info.size.tf.htmlText = this.strSize
					.split("[size]").join(size);
			};
			mc.setSize(items[i].producttype_size_id);
			// Creates the data provider for the combo box.
			var dataProvider:Array = new Array();
			// Adds all sizes.
			for(var j:Number = 0; j < mc.sizes.length; j++) {
				dataProvider.push({
					data: mc.sizes[j].producttype_size_id,
					label: mc.sizes[j].name
				});
			}
			mc.sizesDataProvider = dataProvider;
			// Setup info movie clip.
			mc.info.isOver = false;
			mc.info.gotoAndStop(1);
			// Setup hit area.
			mc.area.shoppingCart = this;
			mc.area.onRollOver = function():Void {
				var info:MovieClip = this._parent.info;
				info.isOver = true;
				info.play();
			};
			mc.area.onRollOut = mc.area.onDragOut = function():Void {
				var info:MovieClip = this._parent.info;
				if(!this._parent.isSelected) {
					info.isOver = false;
				}
			};
			mc.area.onPress = function():Void {
				this.shoppingCart.selectItem(this._parent.id);
				// Show item in detal view.
				this.shoppingCart._gui.showItem(
					this._parent.values.article_id,
					this._parent.values.producttype_size_id,
					this._parent.values.quantity
				);
			};
			// Setup the filter effects.
		    var filShadow:DropShadowFilter = Module.FILTER_SUB_SHADOW;
		    var filArray:Array = new Array();
		    filArray.push(filShadow);
		    mc.base.filters = filArray;
			// Enable caching.
			mc.cacheAsBitmap = true;

			// Save some data for various usage.
			mc.values = new Object();
			mc.values.article_id = items[i].article_id;
			mc.values.basketitem_id = items[i].basketitem_id;
			mc.values.quantity = items[i].quantity;
			mc.values.producttype_size_id = items[i].producttype_size_id;
			// Reset item properties and enable selected item.
			mc.isSelected = false;
			if(mc.values.basketitem_id == _selectedItem) {
				mc.isSelected = true;
				mc.isOver = true;
				mc.area.onRollOver();
				// Show options.
				setupOptions(true);
			}
			// Add item to items list.
			_items.push(mc);
		}
		// Setup scrollbar.
		var isVisible:Boolean = (items.length > 3);
		var scrollbar:ScrollBar = new ScrollBar(
			_gui,
			_clip.shoppingCart.scrollbar,
			clip,
			isVisible
		);
	}

	/**
	 * Select the item.
	 */
	private function selectItem(item_id:Number):Void {
		// Select item and deselect all other items.
		// If item is already selected, deselect it.
		setupOptions(false);
		for(var i:Number = 0; i < _items.length; i++) {
			var mc:MovieClip = _items[i];
			if((i == item_id)
				&& (_selectedItem != mc.values.basketitem_id)
			) {
				mc.isSelected = true;
				mc.isOver = true;
				mc.area.onRollOver();
				_selectedItem = mc.values.basketitem_id;
				_selectedClip = mc;
				setupOptions(true);
				Logger.getLog().info("Select basket item: "
					+ _selectedItem);
			} else {
				mc.isSelected = false;
				mc.isOver = false;
				mc.area.onRollOut();
				if(_selectedItem == mc.values.basketitem_id) {
					_selectedItem = null;
					_selectedClip = undefined;
				}
			}
		}
	}

	/**
	 * Setup options settings.
	 */
	private function setupOptions(onoff:Boolean):Void {
		// Creates an alias to the options movie clip.
		var options:MovieClip = _clip.shoppingCart.options;
		var options_bg:MovieClip = _clip.shoppingCart.ground.options;
		// Show or hide options.
		options._visible = onoff;
		options_bg._visible = onoff;
		if(onoff) {
			// Setup the sizes combobox.
			var sizeComboBox:ComboBox = options.sizes;
			var sizes:Array = _selectedClip.sizesDataProvider;
			sizeComboBox._lockroot = true;
			sizeComboBox.tabEnabled = false;
			sizeComboBox.dataProvider = sizes;
			sizeComboBox.rowCount = sizes.length;
			for(var i:Number = 0; i < sizes.length; i++) {
				var id:Number = _selectedClip.values.producttype_size_id;
				if(sizes[i].data == id) {
					sizeComboBox.selectedIndex = i;
					break;
				}
			}
			sizeComboBox.setStyle("color", "0x0099ff");
			var sizeComboBoxListener:Object = new Object();
			sizeComboBoxListener.shoppingCart = this;
			sizeComboBoxListener.change = function(evt:Object):Void {
				var clp:MovieClip = this.shoppingCart._selectedClip;
				var psize_id:Number = evt.target.selectedItem.data;
				// for changing realtime: clp.setSize(producttype_size_id);
				clp.values.producttype_size_id = psize_id;
			};
			sizeComboBox.addEventListener("change", sizeComboBoxListener);
			// Setup quantity selector.
			var quantitySelector:NumericStepper = options.quantity;
			quantitySelector.tabEnabled = false;
			quantitySelector.minimum = 1;
			quantitySelector.maximum = 99;
			quantitySelector.value = _selectedClip.values.quantity;
			quantitySelector.setStyle("color", "0x0099ff");
			var quantitySelectorListener:Object = new Object();
			quantitySelectorListener.shoppingCart = this;
			quantitySelectorListener.change = function(evt:Object):Void {
				var clp:MovieClip = this.shoppingCart._selectedClip;
				var quantity:Number = evt.target.value;
				// for changing realtime: clp.setQuantity(quantity);
				clp.values.quantity = quantity;
			};
			quantitySelector.addEventListener(
				"change",
				quantitySelectorListener
			);
			// Setup the update button -
			// sets the modified values to the selected item of the basket.
			var btupdate:MovieClip = options.btupdate;
			btupdate.tabEnabled = false;
			btupdate.shoppingCart = this;
			btupdate.onPress = function():Void {
				var clp:MovieClip = this.shoppingCart._selectedClip;
				this.shoppingCart._gui.modifyItem(
					clp.values.basketitem_id,
					clp.values.quantity,
					clp.values.producttype_size_id,
					null // the color id - for future use.
				);
			};
			// Setup the button to remove the selected item from basket.
			var btremove:MovieClip = options.btremove;
			btremove.tabEnabled = false;
			btremove.shoppingCart = this;
			btremove.onPress = function():Void {
				var id:Number = this.shoppingCart._selectedItem;
				if(id != null) {
					this.shoppingCart._gui.removeItem(id);
				} else {
					Logger.getLog().info("No item selected");
				}
			};
		}
	}

	/**
	 * Load the item picture
	 */
	 private function loadItemPic(clip:MovieClip, item:Object):Void {
		// Shows loader animation while loading is in progress.
		var loaderAni:LoaderAnimation = new LoaderAnimation(clip.loader);
		var mclListener:Object = new Object();
		mclListener.loader = loaderAni;
		mclListener.onLoadInit = function(target:MovieClip):Void {
			var mc:MovieClip = target._parent;
			// Stops the loader animation.
			this.loader.removeAnimation();
			// Fade in picture.
			mc.pic._visible = true;
			mc.pic._alpha = 0;
			mc.pic.onEnterFrame = function():Void {
				if((this._alpha += 10) > 90) {
					this._alpha = 100;
					this._parent.loader._visible = false;
					delete this.onEnterFrame;
				}
			};
		};
		// Creates loader an attach listener object.
		var mcLoader:MovieClipLoader = new MovieClipLoader();
		mcLoader.addListener(mclListener);
		// Starts loading.
		mclListener.loader.createAnimation();
		mcLoader.loadClip(item.image_url, clip.pic);
	}

	/*
	 * Transforms the gross.
	 * i.e. converts Number(16.9) to String("16,90")
	 */
	private static function transformGross(nGross:Number):String {
		var a:String = Math.round(nGross * 100).toString();
		return a.substring(0, a.length-2 ) + "," + a.substr(-2);
	}
	
}
